#include <stdarg.h>

#include "gw-device.h"

#include "nvs_flash.h"
#include "nvs.h"

char nvs_settings_name[] = SETTINGS_NAME;//Device-Settings
char device_settings_key[] = "device_settings";
static config_para_t s_device_settings;
nvs_handle my_handle;

static bool enable_debug = false;

uint8_t gw_status = 0;

//return:[FFFC]+[MAC-ADR]
uint64_t getDeviceID(void)
{
    uint8_t mac[6] = {0};
    esp_efuse_mac_get_default(mac);

    // ESP_LOGI("MAC-ADR","MAC:%.2x%.2x%.2x%.2x%.2x%.2x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
    
    uint64_t deviceID = 0;
    deviceID |= ((uint64_t)0xff)<<56;
    deviceID |= ((uint64_t)0xfc)<<48;
    deviceID |= ((uint64_t)mac[0])<<40;
    deviceID |= ((uint64_t)mac[1])<<32;
    deviceID |= ((uint64_t)mac[2])<<24;
    deviceID |= ((uint64_t)mac[3])<<16;
    deviceID |= ((uint64_t)mac[4])<<8;
    deviceID |= ((uint64_t)mac[5]);

    return deviceID;
}

void CON_PRINTF_ARRAY(char* buf,uint16_t size)      
{
    if(enable_debug)
    {
        for(int i = 0;i<size;i++)
            printf("%.2x ",buf[i]);

        printf("\n");
    }

}

int debug_printf(const char *format,...)
{
    int n = 0;
    if(enable_debug)
    {
        va_list list;
        va_start(list,format);
        n=vprintf(format,list);
        va_end(list);

    }
        // printf(format);

    return n;
}

void switch_debug(bool enable)
{
    enable_debug = enable;
}

bool get_debug_state(void)
{
    return enable_debug;
}


esp_err_t read_settings_from_nvs(void)
{
    esp_err_t err;
    char TAG[] = "RD_SETS";

    memset(&s_device_settings,0,sizeof(config_para_t));

    // Open
    err = nvs_open(nvs_settings_name, NVS_READWRITE, &my_handle);
    if (err != ESP_OK) return err;

    // Read the size of memory space required for blob
    size_t required_size = 0;  // value will default to 0, if not set yet in NVS
    err = nvs_get_blob(my_handle, device_settings_key, NULL, &required_size);
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;

    if(required_size == 0)
    {
        ESP_LOGW(TAG,"no config in nvs");
        memcpy(s_device_settings.dataServer_ip,"39.97.178.199",strlen("39.97.178.199"));
        memcpy(s_device_settings.dataServer_port,"1700",strlen("1700"));

        s_device_settings.rf_freq = 477700000;
        s_device_settings.sf = 7;

        memcpy(s_device_settings.wifi_info.ssid,"default",strlen("default"));
        memcpy(s_device_settings.wifi_info.password,"default",strlen("default"));

        s_device_settings.wifi_info.wifi_timeout = 10000;//设置wifi超时时间为10000ms

        memcpy(s_device_settings.network_connecting_priority,"weg",strlen("weg"));
    }
    else
    {
        ESP_LOGI(TAG,"config exist in nvs");
        err = nvs_get_blob(my_handle, device_settings_key, &s_device_settings, &required_size);
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;    

        // Close
        nvs_close(my_handle);

    }

    return err;

}

void get_device_settings(config_para_t* device_settings)
{
    *device_settings = s_device_settings;
}

esp_err_t save_device_settings(void)
{
    esp_err_t err;
    char TAG[] = "SV_SETS";

    // Open
    err = nvs_open(nvs_settings_name, NVS_READWRITE, &my_handle);
    if (err != ESP_OK) return err;

    ESP_LOGI(TAG,"WRITE CONFIG TO NVS");

    // Write value including previously saved blob if available
    err = nvs_set_blob(my_handle, device_settings_key, &s_device_settings, sizeof(config_para_t));
    if (err != ESP_OK) return err;

            // Commit
    err = nvs_commit(my_handle);
    if (err != ESP_OK) return err;

    // Close
    nvs_close(my_handle);

    ESP_LOGI("SV-SETS","save_device_settings success");

    return err;

}

esp_err_t restore_factory_settings(void)
{
    esp_err_t err;
    char TAG[] = "RE_SETS";

    err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // NVS partition was truncated and needs to be erased
        // Retry nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK( err );

    // Open
    err = nvs_open(nvs_settings_name, NVS_READWRITE, &my_handle);
    if (err != ESP_OK) return err;

    err = nvs_erase_all(my_handle);
    if (err != ESP_OK) return err;

    // Commit
    err = nvs_commit(my_handle);
    if (err != ESP_OK) return err;

    // Close
    nvs_close(my_handle);

    read_settings_from_nvs();//

    ESP_LOGI(TAG,"restore success");

    return err;

}

void set_device_settings(config_para_t* device_settings)
{
    s_device_settings = *device_settings;
}

void printf_device_settings(config_para_t* device_settings,bool isPrintaBaseinfo, bool isPrintWIFIInfo)
{
    printf("****************Base info*******************\n");
    printf("\tDataSVR_ip:\t%s\n",device_settings->dataServer_ip);
    printf("\tDataSVR_port:\t%s\n",device_settings->dataServer_port);
    printf("\tRF-freq:\t%d\n",device_settings->rf_freq);
    printf("\tRF-sf:\t\t%d\n",device_settings->sf);
    printf("\tConnect-seq:\t%s\n",device_settings->network_connecting_priority);

    if(isPrintWIFIInfo)
    {
        printf("****************WIFI************************\n");
        printf("\tSSID:\t\t%s\n",device_settings->wifi_info.ssid);
        printf("\tPassword:\t%s\n",device_settings->wifi_info.password);
        printf("\tTimeout:\t%d\n",device_settings->wifi_info.wifi_timeout);
    }

}


void set_gwStatus(gw_status_t status)
{
    gw_status = status;
}

gw_status_t get_gwStatus(void)
{
    return gw_status;
}

uint32_t get_GWMPTick()
{
    return xTaskGetTickCount()%2100000;
}